`timescale 1ns / 1ps
// n4fpga.v - Top level module for the ECE 544 Project 2
//
// Created By:	Rohit Kulkarni, Raviraj Kokil
// Date:		19-February-2015
// Version:		1.0
//
//  Acknowledgement: This file is a modified version for project 1 originally written by Prof. Roy Kravitz
//
// Description:
// ------------
// This module provides the top level for the Project 2 hardware.
// The module assume that a PmodCLP is plugged into the JA and JB
// expansion ports and that a PmodENC is plugged into the JD expansion 
// port (bottom row).
// JC_2 should have been connected to the PWM output to the amber LED.
// JC_3 should have been connected to the sensor output which is an input to the Nexys 4 board.
//
// Project 2 involves closed loop control of the light intensity of the LED.
// Frequency detection is done using hardware and closed loop control is implemented in the Microblaze.  
//  
//////////////////////////////////////////////////////////////////////
module n4fpga(
    input				clk,			// 100MHz clock input
    input				btnC,			// center pushbutton
    input				btnU,			// UP (North) pusbhbutton
    input				btnL,			// LEFT (West) pushbutton
    input				btnD,			// DOWN (South) pushbutton  - used for system reset
    input				btnR,			// RIGHT (East) pushbutton
	input				btnCpuReset,	// CPU reset pushbutton
    input	[15:0]		sw,				// slide switches on Nexys 4
    output	[15:0] 		led,			// LEDs on Nexys 4   
    output              RGB1_Blue,      // RGB1 LED (LD16) 
    output              RGB1_Green,
    output              RGB1_Red,
    output              RGB2_Blue,      // RGB2 LED (LD17)
    output              RGB2_Green,
    output              RGB2_Red,
    output [7:0]        an,             // Seven Segment display
    output [6:0]        seg,
    output              dp,
    
    input				uart_rtl_rxd,	// USB UART Rx and Tx on Nexys 4
    output				uart_rtl_txd,	
    
    output	[7:0] 		JA,				// JA Pmod connector - PmodCLP data bus
										// both rows are used
    output	[7:0] 		JB,				// JB Pmod connector - PmodCLP control signals
										// only the bottom row is used
    output  JC_2,                       //PWM output = sensor input
    input 	JC_3,                       //sensor out = input to Nexys 4 Input				
			
	input	[7:0]		JD				// JD Pmod connector - PmodENC signals
);

// internal variables
wire				sysclk;
wire				sysreset_n, sysreset;
wire				rotary_a, rotary_b, rotary_press, rotary_sw;
wire	[7:0]		lcd_d;
wire				lcd_rs, lcd_rw, lcd_e;

wire	[7:0]	    gpio_in;				// embsys GPIO input port
wire	[7:0]	    gpio_out;				// embsys GPIO output port
wire                pwm_out;                // PWM output from the axi_timer

wire                clk_HW_PWD;             // wire for clock input to the HW PWD logic
wire                HW_PWD_intr;            // wire for Hardware Pulse Width Detection Module
wire    [31:0]      HW_PWD_low_count;       // low level count for Hardware Pulse Width Detection 
wire    [31:0]      HW_PWD_high_count;      // high level count for Hardware Pulse Width Detection
wire                sensor_out;             // light sensor output 

//wrap the pwm_out from the timer back to the application program for software pulse-width detect
assign gpio_in = {7'b0000000, pwm_out};

// The FIT interrupt routine synthesizes a 20KHz signal and makes it
// available on GPIO2[0].  Bring it to the top level as an
// indicator that the system is running...could be handy for debug
wire            clk_20khz;
assign clk_20khz = gpio_out[0];

// We want to show the PWM output on LD15 (the leftmost LED;  The higher the PWM
// duty cycle, the brighter the LED but, the LEDs are controlled by the 
// Microblaze through Nexys4.  So, we have to play some games.  Instead of
// driving the leds directly, we will write 0 to led[15] and then OR in the PWM
// output. 
wire    [15:0]  led_int;                // Nexys4IO drives these outputs
assign led = {(pwm_out | led_int[15]), led_int[14:0]};  // LEDs are driven by led

// make the connections

// system-wide signals
assign sysclk = clk;
assign sysreset_n = btnCpuReset;		// The CPU reset pushbutton is asserted low.  The other pushbuttons are asserted high
										// but the microblaze for Nexys 4 expects reset to be asserted low
assign sysreset = ~sysreset_n;			// Generate a reset signal that is asserted high for any logic blocks expecting it.

// PmodCLP signals
// JA - top and bottom rows
// JB - bottom row only
assign JA = lcd_d[7:0];
assign JB = {1'b0, lcd_e, lcd_rw, lcd_rs, 2'b000, clk_20khz, pwm_out};

// PmodENC signals
// JD - bottom row only
// Pins are assigned such that turning the knob to the right
// causes the rotary count to increment.
assign rotary_a = JD[5];
assign rotary_b = JD[4];
assign rotary_press = JD[6];
assign rotary_sw = JD[7];

// JC[2] used for PWM output to the amber LED
assign  JC_2      = pwm_out;       //PWM output = sensor input
// JC[3] used for sensor output coming into Nexys 4
assign  sensor_out = JC_3;         //sensor out = input to Nexys 4 Input                
			
// instantiate the embedded system
system EMBSYS
       (.PmodCLP_DataBus(lcd_d),        //LCD data bus
        .PmodCLP_E(lcd_e),              //LCD enable 
        .PmodCLP_RS(lcd_rs),            //LCD register select
        .PmodCLP_RW(lcd_rw),            //LCD read/write
        .PmodENC_A(rotary_a),           
        .PmodENC_B(rotary_b),
        .PmodENC_BTN(rotary_press),
        .PmodENC_SWT(rotary_sw),
        .RGB1_Blue(RGB1_Blue),
        .RGB1_Green(RGB1_Green),
        .RGB1_Red(RGB1_Red),
        .RGB2_Blue(RGB2_Blue),
        .RGB2_Green(RGB2_Green),
        .RGB2_Red(RGB2_Red),
        .an(an),
        .btnC(btnC),
        .btnD(btnD),
        .btnL(btnL),
        .btnR(btnR),
        .btnU(btnU),
        .dp(dp),
        .led(led_int),
        .seg(seg),
        .sw(sw),
        .sysreset_n(sysreset_n),
        .sysclk(sysclk),
        .uart_rtl_rxd(uart_rtl_rxd),
        .uart_rtl_txd(uart_rtl_txd),
        .gpio_0_GPIO2_tri_o(gpio_out),
        .gpio_0_GPIO_tri_i(gpio_in),
        .gpio_1_GPIO2_tri_i(HW_PWD_high_count),
        .gpio_1_GPIO_tri_i(HW_PWD_low_count),
        .pwm0(pwm_out),                 //PWM out connected to JC to drive the amber LED
        .clk_out2(clk_HW_PWD),
        .In2(1'b0),                     //HWPWD optional interrupt disabled
        .pwm_in(sensor_out));           //light sensor output connected here

endmodule
